package org.cyrano.bcol;

import java.util.ArrayList;
import java.util.List;

import org.cyrano.bcol.base.CollisionDetector;
import org.cyrano.bcol.base.CollisionDetector.CollisionInfo;
import org.cyrano.bcol.base.CollisionDetector.Side;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.view.MotionEvent;
import android.view.View;

/**
 * @author Demián Gutierrez
 */
public class CustomDrawView extends View {

  // --------------------------------------------------------------------------------

  protected void onDraw(Canvas canvas) {
    paint(canvas);
  }

  // --------------------------------------------------------------------------------
  // --------------------------------------------------------------------------------
  // --------------------------------------------------------------------------------
  // --------------------------------------------------------------------------------
  // --------------------------------------------------------------------------------

  public static final int BOX1_COLOR = Color.RED;
  public static final int BOX2_COLOR = Color.GREEN;

  private List<BoxImpl> boxList = new ArrayList<BoxImpl>();

  private BoxImpl box1;
  private BoxImpl box2;

  private boolean start;

  private BoxImpl dragBox;

  private int dx;
  private int dy;

  private double grayTimeFactor = 1;

  // --------------------------------------------------------------------------------

  public CustomDrawView(Context context) {
    super(context);

    box1 = new BoxImpl();

    box1.cx = 10;
    box1.cy = 300;
    box1.bw = 75;
    box1.bh = 50;
    box1.sx = 260;
    box1.sy = 100;

    box1.calcV();

    boxList.add(box1);

    // ----------------------------------------

    box2 = new BoxImpl();

    box2.cx = 20;
    box2.cy = 100;
    box2.bw = 50;
    box2.bh = 75;
    box2.sx = 260;
    box2.sy = 300;

    box2.calcV();

    boxList.add(box2);

    // ----------------------------------------

    //    addMouseListener(new MouseAdapter() {
    //      @Override
    //      public void mousePressed/* */(MouseEvent evt) {
    //        GamePanel.this.mousePressed/* */(evt);
    //      }
    //
    //      @Override
    //      public void mouseReleased/**/(MouseEvent evt) {
    //        GamePanel.this.mouseReleased/**/(evt);
    //      }
    //    });
    //
    //    addMouseMotionListener(new MouseMotionAdapter() {
    //      @Override
    //      public void mouseDragged/* */(MouseEvent evt) {
    //        GamePanel.this.mouseDragged/* */(evt);
    //      }
    //    });
  }

  public boolean onTouchEvent(MotionEvent evt) {
    switch (evt.getAction()) {
      case MotionEvent.ACTION_DOWN :
        mousePressed(evt);
        break;
      case MotionEvent.ACTION_MOVE :
        mouseDragged(evt);
        break;
      case MotionEvent.ACTION_UP :
        mouseReleased(evt);
        break;
      default :
        break;
    }

    return true;
  }

  // --------------------------------------------------------------------------------

  //  public void setGrayTimeFactor(double grayTimeFactor) {
  //    this.grayTimeFactor = grayTimeFactor;
  //
  //    repaint();
  //  }

  // --------------------------------------------------------------------------------

  private void drawBox(Canvas g2d, BoxImpl box, int color) {
    Paint paint = new Paint();
    paint.setStyle(Paint.Style.STROKE);

    paint.setColor(Color.CYAN);
    //g2d.drawRect((int) box.sx, (int) box.sy, (int) (box.sx + box.bw), (int) (box.sy + box.bh), paint);
    g2d.drawRect((int) box.sx, (int) box.sy, (int) (box.sx + box.bw), (int) (box.sy + box.bh), paint);

    paint.setColor(color);
    g2d.drawRect((int) box.cx, (int) box.cy, (int) (box.cx + box.bw), (int) (box.cy + box.bh), paint);

    Point beg1 = new Point();
    Point end1 = new Point();
    Point beg2 = new Point();
    Point end2 = new Point();

    if (box.cx < box.sx) {
      if (box.cy < box.sy) {
        beg1.set(box.cx, box.cy + box.bh);
        end1.set(box.sx, box.sy + box.bh);

        beg2.set(box.cx + box.bw, box.cy);
        end2.set(box.sx + box.bw, box.sy);
      } else if (box.cy == box.sy) {
        beg1.set(box.cx + box.bw, box.cy + box.bh);
        end1.set(box.sx, box.sy + box.bh);

        beg2.set(box.cx + box.bw, box.cy);
        end2.set(box.sx, box.sy);
      } else {
        beg1.set(box.cx + box.bw, box.cy + box.bh);
        end1.set(box.sx + box.bw, box.sy + box.bh);

        beg2.set(box.cx, box.cy);
        end2.set(box.sx, box.sy);
      }
      // -------------------------------------------
    } else if (box.cx == box.sx) {
      if (box.cy < box.sy) {
        beg1.set(box.cx, box.cy + box.bh);
        end1.set(box.sx, box.sy);

        beg2.set(box.cx + box.bw, box.cy + box.bh);
        end2.set(box.sx + box.bw, box.sy);
      } else if (box.cy == box.sy) {
        // NONE
      } else {
        beg1.set(box.sx, box.sy + box.bh);
        end1.set(box.cx, box.cy);

        beg2.set(box.sx + box.bw, box.sy + box.bh);
        end2.set(box.cx + box.bw, box.cy);
      }
      // -------------------------------------------
    } else {
      if (box.cy < box.sy) {
        beg1.set(box.sx, box.sy);
        end1.set(box.cx, box.cy);

        beg2.set(box.sx + box.bw, box.sy + box.bh);
        end2.set(box.cx + box.bw, box.cy + box.bh);
      } else if (box.cy == box.sy) {
        beg1.set(box.sx + box.bw, box.sy);
        end1.set(box.cx, box.cy);

        beg2.set(box.sx + box.bw, box.sy + box.bh);
        end2.set(box.cx, box.cy + box.bh);
      } else {
        beg1.set(box.cx + box.bw, box.cy);
        end1.set(box.sx + box.bw, box.sy);

        beg2.set(box.cx, box.cy + box.bh);
        end2.set(box.sx, box.sy + box.bh);
      }
    }

    if (beg1 != null && end1 != null) {
      paint.setColor(Color.WHITE);
      g2d.drawLine(beg1.x, beg1.y, end1.x, end1.y, paint);
    }
    if (beg2 != null && end2 != null) {
      paint.setColor(Color.WHITE);
      g2d.drawLine(beg2.x, beg2.y, end2.x, end2.y, paint);
    }
  }

  // --------------------------------------------------------------------------------

  private void drawBox(Canvas g2d, BoxImpl box, int color, CollisionInfo ci) {
    Paint paint = new Paint();
    paint.setStyle(Paint.Style.STROKE);

    int x, y, w, h;

    if (ci.time != Double.MAX_VALUE) {
      x = (int) (box.cx + box.vx * ci.time * grayTimeFactor);
      y = (int) (box.cy + box.vy * ci.time * grayTimeFactor);
    } else {
      x = (int) (box.cx + box.vx * 1 * grayTimeFactor);
      y = (int) (box.cy + box.vy * 1 * grayTimeFactor);
    }

    w = box.bw;
    h = box.bh;

    paint.setColor(Color.GRAY);
    g2d.drawRect(x, y, x + w, y + h, paint);

    x = (int) (box.cx + box.vx * ci.time);
    y = (int) (box.cy + box.vy * ci.time);
    w = box.bw;
    h = box.bh;

    paint.setColor(color);
    g2d.drawRect(x, y, x + w, y + h, paint);

    Side side = null;

    if (box == ci.box1) {
      side = ci.box1Side;
    }

    if (box == ci.box2) {
      side = ci.box2Side;
    }

    if (side != null) {
      paint.setColor(Color.WHITE);

      switch (side) {
        case LFT :
          g2d.drawLine(x,/* */y,/* */x,/* */y + h, paint);
          break;

        case RGH :
          g2d.drawLine(x + w, y,/* */x + w, y + h, paint);
          break;

        case TOP :
          g2d.drawLine(x,/* */y,/* */x + w, y/**/, paint);
          break;

        case BOT :
          g2d.drawLine(x,/* */y + h, x + w, y + h, paint);
          break;
      }
    }
  }

  // --------------------------------------------------------------------------------
  // JPanel
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // XXX: Old swing code, it was migrated 1:1, so fix it in the android way
  // --------------------------------------------------------------------------------

  public void paint(Canvas g) {
    update(g);
  }

  public void update(Canvas g) {
    //    Graphics2D g2d = (Graphics2D) g;
    Canvas g2d = g;

    //    g2d.setBackground(Color.BLACK);
    //    g2d.clearRect(0, 0, Hwh.getW(this), Hwh.getH(this));
    Paint paint = new Paint();
    paint.setStyle(Paint.Style.FILL_AND_STROKE);

    paint.setColor(Color.BLACK);
    g2d.drawRect(0, 0, Hwh.getW(this), Hwh.getH(this), paint);

    CollisionInfo ci = new CollisionInfo(box1, box2);
    CollisionDetector.calcTimeToCollide(ci);

    System.err.println(ci);

    drawBox(g2d, box1, BOX1_COLOR);
    drawBox(g2d, box2, BOX2_COLOR);

    drawBox(g2d, box1, BOX1_COLOR, ci);
    drawBox(g2d, box2, BOX2_COLOR, ci);
  }

  // --------------------------------------------------------------------------------
  // Mouse handling
  // --------------------------------------------------------------------------------

  private void mousePressed(MotionEvent evt) {
    for (BoxImpl box : boxList) {
      Rect r;

      r = new Rect(box.cx, box.cy, box.cx + box.bw, box.cy + box.bh);

      if (r.contains((int) evt.getX(), (int) evt.getY())) {
        dx = (int) (evt.getX() - box.cx);
        dy = (int) (evt.getY() - box.cy);
        dragBox = box;
        start = true;
        return;
      }

      r = new Rect(box.sx, box.sy, box.sx + box.bw, box.sy + box.bh);

      if (r.contains((int) evt.getX(), (int) evt.getY())) {
        dx = (int) (evt.getX() - box.sx);
        dy = (int) (evt.getY() - box.sy);
        dragBox = box;
        start = false;
        return;
      }
    }
  }

  // --------------------------------------------------------------------------------

  private void mouseReleased(MotionEvent evt) {
    dragBox = null;
  }

  // --------------------------------------------------------------------------------

  private void mouseDragged(MotionEvent evt) {
    if (dragBox == null) {
      return;
    }

    if (start) {
      dragBox.cx = (int) (evt.getX() - dx);
      dragBox.cy = (int) (evt.getY() - dy);
    } else {
      dragBox.sx = (int) (evt.getX() - dx);
      dragBox.sy = (int) (evt.getY() - dy);
    }

    dragBox.calcV();

    invalidate();
  }
}
